// import type { Plugin } from 'vue'
import Decimal from 'decimal.js'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
const permissionStore = usePermissionStoreWithOut()
// 验证是否为blob格式
export function blobValidate(data: { type: string }) {
  return data.type !== 'application/json'
}

//判断数组每一项指定字段是否相同
export const areIdsEqual = (array: any[], key?: string) => {
  const firstId = array[0][key ?? 'id']
  return array.every((item: Record<string, any>) => item[key ?? 'id'] === firstId)
}

//根据接口枚举匹配出中文名称
export const useEnumeratePicker = (
  enumList: any[],
  field: string | number,
  key?: string,
  value?: string
) => {
  if (!enumList) return
  const matchItem =
    enumList.find((item: Record<string, any>) => item[value ?? 'value'] === field) || {}
  return matchItem[key ?? 'label'] || ''
}

export const useEnumerateMultiplePicker = (
  enumList: any[],
  field: string | null | undefined,
  key?: string,
  value?: string
) => {
  field = field ?? ''

  // 确保 partner 是一个有效的字符串
  return field.length > 0
    ? field
        .split(',')
        .map((item) => useEnumeratePicker(enumList, Number(item)))
        .join(', ')
    : ''
}

//千分位自动补逗号
export const formatNumber = (num: string | number) => {
  if (!num) return '0.00'
  return num.toString().replace(/\d+/, function (n) {
    return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
  })
}
/**
 * @description 生成唯一 uuid
 * @returns {String}
 */
export const generateUUID = (): string | undefined => {
  let uuid = ''
  for (let i = 0; i < 32; i++) {
    const random = (Math.random() * 16) | 0
    if (i === 8 || i === 12 || i === 16 || i === 20) uuid += '-'
    uuid += (i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(16)
  }
  return uuid
}
/**
 * @description 一维数组求和
 * @param {Array} arr 传入一维数组，示例arr:[{num:1},{num:2}]
 * @param key 传入对象中需要相加的key参数,key:num
 * @param precision 小数位数
 */
export const oneDimensionalArraySummation = (arr: any[], key: string, precision: number = 2) => {
  return arr.reduce(
    (total, value) => new Decimal(total).add(new Decimal(value[key] || 0)).toFixed(precision),
    0
  )
}

/**
 * @description 一维数组求和
 * @param {Array} arr 传入需要求和的数组，示例：[1,2,3,4,5]
 */
export const sumItem = (arr: any[]) => {
  return arr.reduce((total, value) => new Decimal(total).add(new Decimal(value)).toString(), 0)
}

/**
 *
 * @param component 需要注册的组件
 * @param alias 组件别名
 * @returns any
 */
export const withInstall = <T>(component: T, alias?: string) => {
  const comp = component as any
  comp.install = (app: any) => {
    app.component(comp.name || comp.displayName, component)
    if (alias) {
      app.config.globalProperties[alias] = component
    }
  }
  return component as T & Plugin
}

/**
 * @param str 需要转下划线的驼峰字符串
 * @returns 字符串下划线
 */
export const humpToUnderline = (str: string): string => {
  return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}

/**
 * @param str 需要转驼峰的下划线字符串
 * @returns 字符串驼峰
 */
export const underlineToHump = (str: string): string => {
  if (!str) return ''
  return str.replace(/\-(\w)/g, (_, letter: string) => {
    return letter.toUpperCase()
  })
}

/**
 * 驼峰转横杠
 */
export const humpToDash = (str: string): string => {
  return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}

export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
  dom.style.setProperty(prop, val)
}

export const getCssVar = (prop: string, dom = document.documentElement) => {
  return getComputedStyle(dom).getPropertyValue(prop)
}

/**
 * 查找数组对象的某个下标
 * @param {Array} ary 查找的数组
 * @param {Functon} fn 判断的方法
 */
// eslint-disable-next-line
export const findIndex = <T = Recordable>(ary: Array<T>, fn: Fn): number => {
  if (ary.findIndex) {
    return ary.findIndex(fn)
  }
  let index = -1
  ary.some((item: T, i: number, ary: Array<T>) => {
    const ret: T = fn(item, i, ary)
    if (ret) {
      index = i
      return ret
    }
  })
  return index
}

export const trim = (str: string) => {
  return str.replace(/(^\s*)|(\s*$)/g, '')
}

/**
 * @param {Date | number | string} time 需要转换的时间
 * @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
 */
export function formatTime(time: Date | number | string, fmt: string) {
  if (!time) return ''
  else {
    const date = new Date(time)
    const o = {
      'M+': date.getMonth() + 1,
      'd+': date.getDate(),
      'H+': date.getHours(),
      'm+': date.getMinutes(),
      's+': date.getSeconds(),
      'q+': Math.floor((date.getMonth() + 3) / 3),
      S: date.getMilliseconds()
    }
    if (/(y+)/.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
    }
    for (const k in o) {
      if (new RegExp('(' + k + ')').test(fmt)) {
        fmt = fmt.replace(
          RegExp.$1,
          RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
        )
      }
    }
    return fmt
  }
}

/**
 * 生成随机字符串
 */
export function toAnyString() {
  const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => {
    const r: number = (Math.random() * 16) | 0
    const v: number = c === 'x' ? r : (r & 0x3) | 0x8
    return v.toString()
  })
  return str
}

/**
 * 首字母大写
 */
export function firstUpperCase(str: string) {
  return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase())
}

/**
 * 把对象转为formData
 */
export function objToFormData(obj: Recordable) {
  const formData = new FormData()
  Object.keys(obj).forEach((key) => {
    formData.append(key, obj[key])
  })
  return formData
}

export const calculateColumnWidth = (
  dataList: any[],
  columnKey: string,
  level?: number,
  width?: number
): string => {
  // 假设根据列数据计算宽度，返回一个字符串形式的宽度值
  const maxLength = Math.max(
    ...dataList.map((item) => (item[columnKey] ? item[columnKey].length : 0))
  )
  level = level ?? 1
  return `${maxLength * (width ?? 10) > level * 100 ? maxLength * (width ?? 10) : level * 100}px`
}

export const filterEmptyParams = (params: Record<string, any>) => {
  const filtered: Record<string, any> = {}

  Object.keys(params).forEach((key) => {
    const value = params[key]
    if (
      value !== null &&
      value !== undefined &&
      value !== '' &&
      !(Array.isArray(value) && value.length === 0)
    ) {
      filtered[key] = value
    }
  })

  return filtered
}

/**
 * 生成唯一的文件名
 * @param type 文件的后缀名，必须是字母或数字的组合
 * @returns string
 * @throws Error 非法文件后缀名
 */
export function createFileName(type: string): string {
  if (!/^[a-z0-9]+$/i.test(type)) {
    throw new Error('非法文件后缀名')
  }
  const now = new Date()
  const dateStr = now
    .toISOString()
    .replace(/[-T:.Z]/g, '')
    .slice(0, 14) // yyyyMMddHHmmss
  const ms = Date.now()
  const random = Array.from(crypto.getRandomValues(new Uint8Array(5)))
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('')
  return `${dateStr}${ms}${random}.${type}`
}

/**
 * 构建 OSS 文件路径
 * @param fileName 文件名称
 * @param directory 目录名称
 * @param type 操作类型，可选 thumb|water
 * @returns string
 * @throws Error 文件名或目录名非法
 */
export function createOssFilePath(fileName: string, directory: string, type: string = ''): string {
  const pregMatch = /[^\w.]/
  if (!fileName || pregMatch.test(fileName)) {
    throw new Error('文件名称非法，不可包含特殊符号')
  }
  if (!directory || pregMatch.test(directory)) {
    throw new Error('目录名称非法，不可包含特殊符号')
  }
  const now = new Date()
  const ym = now.getFullYear().toString() + (now.getMonth() + 1).toString().padStart(2, '0')
  const d = now.getDate().toString().padStart(2, '0')
  let filePath = `${directory}/${ym}/${d}`
  switch (type) {
    case 'thumb':
      filePath += `/thumb/thumb_${fileName}`
      break
    case 'water':
      filePath += `/water/water_${fileName}`
      break
    default:
      filePath += `/${fileName}`
      break
  }
  return filePath
}

/**
 * 判断是否拥有权限
 * @param {string[]} permissions 权限列表
 * @returns {boolean} 是否拥有权限
 */
export const hasPermission = (permissionsValue: string[]) => {
  const roleRouterList = permissionStore.$state.addRouters
  // const permission = (router.currentRoute.value.meta.permission || []) as string[]
  // 遍历 roleRouterList 里的 item.children，收集所有 el.meta.permission 组成一个数组
  const permission: string[] = []
  roleRouterList.forEach((item) => {
    if (Array.isArray(item.children)) {
      item.children.forEach((child) => {
        if (child.meta && Array.isArray(child.meta.permission)) {
          permission.push(...child.meta.permission)
        }
      })
    }
  })
  console.log(permission, 'permission_boolean')
  return permissionsValue.some((permi) => {
    const hasPermission = permission.includes(permi)
    return hasPermission
  })
}

/**
 * 处理精度
 * @param data 数据
 * @param precision 精度
 * @returns 处理后的数据
 */
export const processingAccuracy = (data: number, precision: number = 2) => {
  return new Decimal(data).toFixed(precision)
}

// 定义简单的加密方法，实际项目中可根据需求替换为更安全的加密算法
/**
 * 简单的参数加密方法
 * @param value 需要加密的值，支持字符串或数字类型
 * @returns 加密后的字符串
 */
export function encryptParam(value: string | number): string {
  const strValue = String(value)
  // 使用简单的 Base64 编码进行伪装，在 URL 上不会直接显示原始值
  const base64Encoded = btoa(strValue)
  // 简单混淆：将编码后的字符串反转
  const obfuscated = base64Encoded.split('').reverse().join('')
  return obfuscated
}

/**
 * 简单的参数解密方法，与加密方法对应
 * @param encryptedValue 需要解密的字符串
 * @returns 解密后的原始字符串
 */
export function decryptParam(encryptedValue: string): string {
  // 反转字符串恢复 Base64 编码
  const base64Encoded = encryptedValue.split('').reverse().join('')
  // 使用 Base64 解码获取原始值
  const decoded = atob(base64Encoded)
  return decoded
}
